#include <stdio.h>
#include <stdlib.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <unistd.h>

union semun {
    int val;
    struct semid_ds *buf;
    unsigned short *array;
};

int main(int argc, char const *argv[])
{
    struct sembuf P = {0, -1, SEM_UNDO};
    struct sembuf V = {0, 1, SEM_UNDO};

    union semun arg;

    int emptyid = semget(IPC_PRIVATE, 1, IPC_CREAT | 0666);
    int appleid = semget(IPC_PRIVATE, 1, IPC_CREAT | 0666);
    int orangeid = semget(IPC_PRIVATE, 1, IPC_CREAT | 0666);

    arg.val = 1;
    semctl(emptyid, 0, SETVAL, arg);
    arg.val = 0;
    semctl(appleid, 0, SETVAL, arg);
    semctl(orangeid, 0, SETVAL, arg);

    int times = 5;
    if (fork() == 0) {
        while (times--) {
            semop(emptyid, &P, 1);
            puts("==>\tApple\tFather put one apple");
            semop(appleid, &V, 1);
        }
        exit(0);
    } else {
        if (fork() == 0) {
            while (times--) {
                semop(emptyid, &P, 1);
                puts("==>\tOrange\tMother put one orange");
                semop(orangeid, &V, 1);
            }
            exit(0);
        } else {
            if (fork() == 0) {
                while (times--) {
                    semop(appleid, &P, 1);
                    puts("<==\tApple\tDaughter eat one apple");
                    semop(emptyid, &V, 1);
                }
                exit(0);
            } else {
                while (times--) {
                    semop(orangeid, &P, 1);
                    puts("<==\tOrange\tSon eat one orange");
                    semop(emptyid, &V, 1);
                }
            }
        }
    }
    wait(NULL);
    wait(NULL);
    wait(NULL);

    semctl(emptyid, IPC_RMID, 0);
    semctl(appleid, IPC_RMID, 0);
    semctl(orangeid, IPC_RMID, 0);

    return 0;
}
